package I_A.IMS.EUQ.SP;

import ME.VPC.C.skivvy.MakeContainerZNSZ;
import ME.VPC.M.app.App;
import exception.file.O.DetaBufferedReader;
import exception.file.O.DetaInputStreamReader;
import U_A.PEU.P.movie.AdataFrame;
import U_A.PEU.P.movie.Header;
import U_A.PEU.P.movie.MdataFrame;
import U_A.PEU.P.sound.BytestoAIS;
import U_A.PEU.P.wave.DFT;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioFormat.Encoding;
import java.awt.image.BufferedImage;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.RandomAccessFile;

/*
 * 个人著作权人, 作者 罗瑶光, 浏阳
 * yaoguangluo@outlook.com, 313699483@qq.com, 2080315360@qq.com,
 * (lyg.tin@gmail.com2018年回国后因国内G网屏蔽不再使用）
 * 15116110525-浏阳德塔软件开发有限公司-创始人-法人-总经理-永久非盈利-
 * 430181198505250014, G24402609, EB0581342
 * 204925063, 389418686, F2406501, 0626136
 * 湖南省 浏阳市 集里街道 神仙坳社区 大塘冲一段路 208号 阳光家园别墅小区 第十栋别墅 第三层
 * */
public class LYGFileIO {
    public Header header;
    public AdataFrame adataFrame;
    public MdataFrame mdataframe;
    public double duration;
    public String inputPath;
    public String outputPath;
    public int[] fsize;
    public double[]  master;
    public double[]  slave;
    public double[] [] fftmatrix;
    public int[] fftLogCount;
    public BufferedImage image;
    public MakeContainerZNSZ makeContainerZNSZ;

    public LYGFileIO() {
    }

    public LYGFileIO initWithFFT(double fft[], App NE) {
        LYGFileIO lYGFileIO = new LYGFileIO();
        lYGFileIO.makeContainerZNSZ = NE._I_U.makeContainerZNSZ;
        lYGFileIO.header = new Header();
        lYGFileIO.header.MFrameRate = 0;
        lYGFileIO.header.MHFrame = 0;
        lYGFileIO.header.MWFrame = 0;
        lYGFileIO.header.MFrameLeangth = 0;
        lYGFileIO.header.SEn = new Encoding("PCM_SIGNED");
        lYGFileIO.header.SFrameLeangth = 0;
        lYGFileIO.header.SSampleRate = 19200;
        lYGFileIO.header.SSampleSizeInBits = 16;
        lYGFileIO.header.SChannels = 2;
        lYGFileIO.header.SFrameSize = 4;
        lYGFileIO.header.SFrameRate = 19200;
        lYGFileIO.header.SBigEndian = true;
        lYGFileIO.adataFrame = new AdataFrame();
        //lYGFileIO.adataFrame.audioArray= new double[(int)lYGFileIO.header.SFrameRate];
        DFT dFT = new DFT();
        dFT.IV_(1024);
        fft[10] = 10000.0;
        double[]  array = dFT.ft(fft);
        lYGFileIO.adataFrame.audioArray = array;
        lYGFileIO.adataFrame.fftarray = fft;
        AudioFormat af = new AudioFormat(lYGFileIO.header.SEn,
                lYGFileIO.header.SSampleRate,
                lYGFileIO.header.SSampleSizeInBits,
                lYGFileIO.header.SChannels,
                lYGFileIO.header.SFrameSize,
                lYGFileIO.header.SFrameRate,
                lYGFileIO.header.SBigEndian);
        lYGFileIO.IV_ByAudioBytes(af);
//		double times;
//		long milliseconds= (long)((header.SFrameLeangth * 1000)/ header.SFrameRate);
//		lYGFileIO.header.times= milliseconds/ 1000.0;
        return lYGFileIO;
    }

    public void lygRead(String filepath) {
        try {


            //read head by av
            InputStream is = new FileInputStream(filepath);
            String line;
            DetaBufferedReader reader = new DetaBufferedReader(DetaInputStreamReader.E(is));
            while ((line = reader.readDetaLine()) != null) {
                //read head
                if (line.equals("<HEAD>")) {
                    //20230106-S_logger.Log.logger.info("" + "has HEAD");
                    header = new Header();
                }
                if (line.equals("<MFR>")) {
                    line = reader.readDetaLine();
                    header.MFrameRate = Integer.parseInt(line);
                }
                if (line.equals("<MHR>")) {
                    line = reader.readDetaLine();
                    header.MHFrame = Integer.parseInt(line);
                }
                if (line.equals("<MWR>")) {
                    line = reader.readDetaLine();
                    header.MWFrame = Integer.parseInt(line);
                }
                if (line.equals("<MFL>")) {
                    line = reader.readDetaLine();
                    header.MFrameLeangth = Integer.parseInt(line);
                }
                //
                if (line.equals("<AEN>")) {
                    line = reader.readDetaLine();
                    header.SEn = new Encoding(line);
                }
                if (line.equals("<AFL>")) {
                    line = reader.readDetaLine();
                    header.SFrameLeangth = Long.parseLong(line);
                }
                if (line.equals("<ASR>")) {
                    line = reader.readDetaLine();
                    header.SSampleRate = Float.parseFloat(line);
                }
                if (line.equals("<ASS>")) {
                    line = reader.readDetaLine();
                    header.SSampleSizeInBits = Integer.parseInt(line);
                }
                if (line.equals("<ACH>")) {
                    line = reader.readDetaLine();
                    header.SChannels = Integer.parseInt(line);
                }
                if (line.equals("<AFS>")) {
                    line = reader.readDetaLine();
                    header.SFrameSize = Integer.parseInt(line);
                }
                if (line.equals("<AFR>")) {
                    line = reader.readDetaLine();
                    header.SFrameRate = Float.parseFloat(line);
                }
                if (line.equals("<ABE>")) {
                    line = reader.readDetaLine();
                    header.SBigEndian = Boolean.parseBoolean(line);
                }
                //read frame
                if (line.equals("<FRAME>")) {
                    //20230106-S_logger.Log.logger.info("" + "has FRAME");
                }
                if (line.equals("<AF>")) {
                    adataFrame = new AdataFrame();
                    adataFrame.audioArray = new double[(int) header.SFrameRate];
                    int i = 0;
                    while ((!(line = reader.readDetaLine()).equals("</AF>"))
                        && i < (int) header.SFrameRate) {
                        adataFrame.audioArray[i++] = Double.parseDouble(line);
                    }
                    double times;
                    long milliseconds = (long) ((header.SFrameLeangth * 1000) / header.SFrameRate);
                    times = milliseconds / 1000.0;
                    //
                    int cur = (int)times;
                    if (cur < times) {
                        times = cur + 1.0;
                    }
                    for (int i1 = 0; i1 < times; i1++) {
                        adataFrame.next = new AdataFrame();
                        adataFrame.next.prev = adataFrame;
                        adataFrame = adataFrame.next;
                        adataFrame.audioArray = new double[(int) header.SFrameRate];
                        int i2 = 0;
                        line = reader.readDetaLine();
                        while (!(line.equals("</AF>"))
                                && i2 < (int) header.SFrameRate
                                && !line.equals("<MF>")
                        ) {
                            //20230106-S_logger.Log.logger.info("" + i2);
                            adataFrame.audioArray[i2++] = Double.parseDouble(line);
                            line = reader.readDetaLine();
                        }
                    }
                }
                if (line.equals("<MF>")) {
                    int frameID = 0;
                    mdataframe = new MdataFrame();
                    mdataframe.RBGimage = new int[header.MHFrame][header.MWFrame];
                    for (int i = 0; i < header.MHFrame; i++) {
                        for (int j = 0; j < header.MWFrame; j++) {
                            if (!(line = reader.readDetaLine()).equals("</MF>")) {
                                mdataframe.RBGimage[i][j] = Integer.parseInt(line);
                                mdataframe.frameID = frameID++;
                            }
                        }
                    }
                    while (!(line = reader.readDetaLine()).equals("</MF>")) {
                        mdataframe.next = new MdataFrame();
                        mdataframe.next.prev = mdataframe;
                        mdataframe = mdataframe.next;
                        mdataframe.RBGimage = new int[header.MHFrame][header.MWFrame];
                        for (int i = 0; i < header.MHFrame; i++) {
                            for (int j = 0; j < header.MWFrame; j++) {
                                if (!(line = reader.readDetaLine()).equals("</MF>")) {
                                    mdataframe.RBGimage[i][j] = Integer.parseInt(line);
                                    mdataframe.frameID = frameID++;
                                }
                            }
                        }
                    }
                }
            }
            is.close();
            reader.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void reset() {
        header = null;
        adataFrame = null;
        mdataframe = null;
    }

    public void lygWrite(String string) {
        try {
            BufferedWriter wr = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(string), "UTF8"));
            wr.write("<HEAD>" + "\n");
            wr.write("<MFR>\n" + header.MFrameRate + "\n</MFR>\n");
            //20230106-S_logger.Log.logger.info("" + "<MFR>\n"+header.MFrameRate+"\n</MFR>\n");
            wr.write("<MHR>\n" + header.MHFrame + "\n</MHR>\n");
            //20230106-S_logger.Log.logger.info("" + "<MHR>\n"+header.MHFrame+"\n</MHR>\n");
            wr.write("<MWR>\n" + header.MWFrame + "\n</MWR>\n");
            //20230106-S_logger.Log.logger.info("" + "<MWR>\n"+header.MWFrame+"\n</MWR>\n");
            wr.write("<MFL>\n" + header.MFrameLeangth + "\n</MFL>\n");
            //20230106-S_logger.Log.logger.info("" + "<MFL>\n"+header.MFrameLeangth+"\n</MFL>\n");
            //en /1sample rate /2samplesize /3 channels /4framesize  /5 framrate/bigendianture
            wr.write("<AEN>\n" + header.SEn.toString() + "\n</AEN>\n");
            //20230106-S_logger.Log.logger.info("" + "<AEN>\n"+header.SEn.toString()+"\n</AEN>\n");
            wr.write("<ASR>\n" + header.SSampleRate + "\n</ASR>\n");
            //20230106-S_logger.Log.logger.info("" + "<ASR>\n"+header.SSampleRate+"\n</ASR>\n");
            wr.write("<ASS>\n" + header.SSampleSizeInBits + "\n</ASS>\n");
            //20230106-S_logger.Log.logger.info("" + "<ASS>\n"+header.SSampleSizeInBits+"\n</ASS>\n");
            wr.write("<ACH>\n" + header.SChannels + "\n</ACH>\n");
            //20230106-S_logger.Log.logger.info("" + "<ACH>\n"+header.SChannels+"\n</ACH>\n");
            wr.write("<AFS>\n" + header.SFrameSize + "\n</AFS>\n");
            //20230106-S_logger.Log.logger.info("" + "<AFS>\n"+header.SFrameSize+"\n</AFS>\n");
            wr.write("<AFR>\n" + header.SFrameRate + "\n</AFR>\n");
            //20230106-S_logger.Log.logger.info("" + "<AFR>\n"+header.SFrameRate+"\n</AFR>\n");
            wr.write("<ABE>\n" + header.SBigEndian + "\n</ABE>\n");
            //20230106-S_logger.Log.logger.info("" + "<ABE>\n"+header.SBigEndian+"\n</ABE>\n");
            wr.write("<AFL>\n" + header.SFrameLeangth + "\n</AFL>\n");
            //20230106-S_logger.Log.logger.info("" + "<AFL>\n"+header.SFrameLeangth+"\n</AFL>\n");
            wr.write("</HEAD>" + "\n");
            wr.write("<FRAME>" + "\n");
            wr.write("<AF>" + "\n");
            if (adataFrame != null) {
                for (int i = 0; i < adataFrame.audioArray.length; i++) {
                    wr.write(adataFrame.audioArray[i] + "\n");
                }
                while (adataFrame.next != null) {
                    adataFrame = adataFrame.next;
                    for (int i = 0; i < adataFrame.audioArray.length; i++) {
                        wr.write(adataFrame.audioArray[i] + "\n");
                    }

                }
            }
            wr.write("</AF>" + "\n");
            wr.write("<MF>" + "\n");
            long fr = 0;
            if (mdataframe != null) {
                for (int i = 0; i < header.MHFrame; i++) {
                    for (int j = 0; j < header.MWFrame; j++) {
                        wr.write(mdataframe.image.getRGB(j, i) + "\n");
                    }
                }
                fr++;
                wr.write(fr + "\n");
                while (mdataframe.next != null) {
                    mdataframe = mdataframe.next;
                    for (int i = 0; i < header.MHFrame; i++) {
                        for (int j = 0; j < header.MWFrame; j++) {
                            wr.write(mdataframe.image.getRGB(j, i) + "\n");
                        }
                    }
                    fr++;
                    wr.write(fr + "\n");
                }
            }
            wr.write("</MF>" + "\n");
            wr.write("</FRAME>" + "\n");
            wr.flush();
            wr.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void toHead() {
        while (adataFrame != null && adataFrame.prev != null) {
            adataFrame = adataFrame.prev;
        }
        while (mdataframe != null && mdataframe.prev != null) {
            mdataframe = mdataframe.prev;
        }
    }

    public void IV_() {
        toHead();
        AudioFormat af = new AudioFormat(header.SEn,
                header.SSampleRate,
                header.SSampleSizeInBits,
                header.SChannels,
                header.SFrameSize,
                header.SFrameRate,
                header.SBigEndian);
        //en /1sample rate /2samplesize /3 channels /4framesize  /5 framrate /bigendianture
        int times = 0;
        if (adataFrame != null) {
            times++;
            adataFrame.audioIS = new BytestoAIS().getAIS(adataFrame.audioArray, af, adataFrame.audioIS);
            while (adataFrame.next != null) {
                times++;
                adataFrame = adataFrame.next;
                adataFrame.audioIS = new BytestoAIS().getAIS(adataFrame.audioArray, af, adataFrame.audioIS);
            }
        }
        this.duration = (double)times;
        toHead();
    }

    public void IQ_header(RandomAccessFile raf) {
        try {
            header = new Header();
            raf.seek(0);
            long headpos = 0;
            byte[] iv = new byte[4];
            raf.read(iv);
            int f0 = ((int) iv[0] & 0x000000ff);
            int f1 = ((int) iv[1] << 8 & 0x0000ff00);
            int f2 = ((int) iv[2] << 16 & 0x00ff0000);
            int f3 = ((int) iv[3] << 24 & 0xff000000);
            f0 = f3 | f2 | f1 | f0;
            header.MWFrame = f0;
            //20230106-S_logger.Log.logger.info("" + "<MWR>\n"+header.MWFrame+"\n</MWR>\n");

            headpos += 4;
            iv = new byte[4];
            raf.read(iv);
            f0 = ((int) iv[0] & 0x000000ff);
            f1 = ((int) iv[1] << 8 & 0x0000ff00);
            f2 = ((int) iv[2] << 16 & 0x00ff0000);
            f3 = ((int) iv[3] << 24 & 0xff000000);
            f0 = f3 | f2 | f1 | f0;
            header.MHFrame = f0;
            //20230106-S_logger.Log.logger.info("" + "<MWR>\n"+header.MHFrame+"\n</MWR>\n");
            headpos += 4;
            //3
            iv = new byte[4];
            raf.read(iv);
            f0 = ((int) iv[0] & 0x000000ff);
            f1 = ((int) iv[1] << 8 & 0x0000ff00);
            f2 = ((int) iv[2] << 16 & 0x00ff0000);
            f3 = ((int) iv[3] << 24 & 0xff000000);
            f0 = f3 | f2 | f1 | f0;
            header.MFrameLeangth = f0;
            //20230106-S_logger.Log.logger.info("" + "<MWR>\n"+header.MFrameLeangth+"\n</MWR>\n");
            headpos += 4;
            //4
            iv = new byte[4];
            raf.read(iv);
            f0 = (int) iv[0] & 0x000000ff;
            f1 = (int) iv[1] << 8 & 0x0000ff00;
            f2 = (int) iv[2] << 16 & 0x00ff0000;
            f3 = (int) iv[3] << 24 & 0xff000000;
            f0 = f3 | f2 | f1 | f0;
            header.MFrameRate = f0;
            //20230106-S_logger.Log.logger.info("" + "<MWR>\n"+header.MFrameLeangth+"\n</MWR>\n");
            headpos += 4;
            //5
            byte[] size = new byte[1];
            raf.read(size);
            headpos += 1;
            if (size[0] != 0) {
                byte array[] = new byte[size[0] * 2];
                raf.read(array);
                char[] ch = new char[size[0]];
                for (int reg = 0; reg < size[0]; reg++) {
                    int c0 = ((int) array[reg * 2] << 8 & 0xff00);
                    int c1 = (int) array[reg * 2 + 1] & 0x00ff;
                    ch[reg] = (char) (c1 | c0);
                }

                String se = new String(ch);
                header.SEn = new Encoding(se);
                //20230106-S_logger.Log.logger.info("" + "good");
                headpos += array.length;
            }
            //6
            iv = new byte[4];
            raf.read(iv);
            f0 = ((int) iv[0] & 0x000000ff);
            f1 = ((int) iv[1] << 8 & 0x0000ff00);
            f2 = ((int) iv[2] << 16 & 0x00ff0000);
            f3 = ((int) iv[3] << 24 & 0xff000000);
            f0 = f3 | f2 | f1 | f0;
            float fl = Float.intBitsToFloat(f0);//.floatToIntBits(IO.header.SSampleRate);
            header.SSampleRate = fl;
            //20230106-S_logger.Log.logger.info("" + "<MWR>\n"+header.SSampleRate+"\n</MWR>\n");
            headpos += 4;
            //7
            iv = new byte[4];
            raf.read(iv);
            f0 = (int) iv[0] & 0x000000ff;
            f1 = (int) iv[1] << 8 & 0x0000ff00;
            f2 = (int) iv[2] << 16 & 0x00ff0000;
            f3 = (int) iv[3] << 24 & 0xff000000;
            f0 = f3 | f2 | f1 | f0;
            header.SSampleSizeInBits = f0;
            //20230106-S_logger.Log.logger.info("" + "<MWR>\n"+header.SSampleSizeInBits+"\n</MWR>\n");
            headpos += 4;
            //8
            iv = new byte[4];
            raf.read(iv);
            f0 = (int) iv[0] & 0x000000ff;
            f1 = (int) iv[1] << 8 & 0x0000ff00;
            f2 = (int) iv[2] << 16 & 0x00ff0000;
            f3 = (int) iv[3] << 24 & 0xff000000;
            f0 = f3 | f2 | f1 | f0;
            header.SChannels = f0;
            //20230106-S_logger.Log.logger.info("" + "<MWR>\n"+header.SChannels+"\n</MWR>\n");
            headpos += 4;
            //9
            iv = new byte[4];
            raf.read(iv);
            f0 = (int) iv[0] & 0x000000ff;
            f1 = (int) iv[1] << 8 & 0x0000ff00;
            f2 = (int) iv[2] << 16 & 0x00ff0000;
            f3 = (int) iv[3] << 24 & 0xff000000;
            f0 = f3 | f2 | f1 | f0;
            header.SFrameSize = f0;
            //20230106-S_logger.Log.logger.info("" + "<MWR>\n"+header.SFrameSize+"\n</MWR>\n");
            headpos += 4;
            //10
            iv = new byte[4];
            raf.read(iv);
            f0 = ((int) iv[0] & 0x000000ff);
            f1 = ((int) iv[1] << 8 & 0x0000ff00);
            f2 = ((int) iv[2] << 16 & 0x00ff0000);
            f3 = ((int) iv[3] << 24 & 0xff000000);
            f0 = f3 | f2 | f1 | f0;
            fl = Float.intBitsToFloat(f0);//.floatToIntBits(IO.header.SSampleRate);
            header.SFrameRate = fl;
            //20230106-S_logger.Log.logger.info("" + "<MWR>\n"+header.SFrameRate+"\n</MWR>\n");
            headpos += 4;
            //11
            byte[] bein = new byte[1];
            raf.read(bein);
            if (bein[0] == 0) {
                header.SBigEndian = false;
            } else {
                header.SBigEndian = true;
            }
            headpos += 1;
            //12
            byte[] audiopos = new byte[8];
            raf.read(audiopos);
            long l0 = ((long) audiopos[0] & 0x00000000000000ff);
            long l1 = ((long) audiopos[1] & 0x00000000000000ff) << 8;
            long l2 = ((long) audiopos[2] & 0x00000000000000ff) << 16;
            long l3 = ((long) audiopos[3] & 0x00000000000000ff) << 24;
            long l4 = ((long) audiopos[4] & 0x00000000000000ff) << 32;
            long l5 = ((long) audiopos[5] & 0x00000000000000ff) << 40;
            long l6 = ((long) audiopos[6] & 0x00000000000000ff) << 48;
            long l7 = ((long) audiopos[7] & 0x00000000000000ff) << 56;
            l0 = l7 | l6 | l5 | l4 | l3 | l2 | l1 | l0;
            header.SFrameLeangth = l0;
            headpos += 8;
            //13
            audiopos = new byte[16];
            raf.read(audiopos);
            headpos += 16;
            //14
            audiopos = new byte[8];
            raf.read(audiopos);
            l0 = ((long) audiopos[0] & 0x00000000000000ff);
            l1 = ((long) audiopos[1] & 0x00000000000000ff) << 8;
            l2 = ((long) audiopos[2] & 0x00000000000000ff) << 16;
            l3 = ((long) audiopos[3] & 0x00000000000000ff) << 24;
            l4 = ((long) audiopos[4] & 0x00000000000000ff) << 32;
            l5 = ((long) audiopos[5] & 0x00000000000000ff) << 40;
            l6 = ((long) audiopos[6] & 0x00000000000000ff) << 48;
            l7 = ((long) audiopos[7] & 0x00000000000000ff) << 56;
            l0 = l7 | l6 | l5 | l4 | l3 | l2 | l1 | l0;
            header.SWavPos = l0;
            headpos += 8;
            header.MovPos = headpos;
            duration = (double)(header.MFrameLeangth / header.MFrameRate);
            //20230106-S_logger.Log.logger.info("" + "end header get");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void IV_ByAudioBytes(AudioFormat af) {
        //en /1sample rate /2samplesize /3 channels /4framesize  /5 framrate /bigendianture
        adataFrame.audioIS = new BytestoAIS().getAIS(adataFrame.fftarray, af, adataFrame.audioIS);
        // TODO Auto - generated method stub

    }
}
